<!-- eslint-disable vue/valid-v-bind -->
<template>
  <div class="formContainer">
    <div
      v-for="(formPanel, formIndex) in option"
      :key="formIndex"
      class="formPanel"
    >
      <!-- 标题 插槽 -->
      <div class="tltle">
        <slot
          v-if="formPanel.titleSlotName"
          :name="formPanel.titleSlotName"
          :[formPanel.titleSlotName]="formPanel"
        />
        <span v-else>{{ formPanel.title || '' }}</span>
      </div>
      <div class="formBody">
        <c-form
          ref="ruleForm"
          :disabled="readonly"
          :label-position="labelPosition || 'left'"
          :model="formData[formIndex]"
          :rules="rules[formIndex]"
          :label-width="labelWidth || '100px'"
          class="demo-ruleForm"
        >
          <c-row v-for="(row, rowIndex) in formPanel.formItem" :key="rowIndex">
            <c-col
              v-for="(col, colIndex) in row"
              :key="colIndex"
              :span="col.span || 24 / row.length"
            >
              <c-form-item
                v-if="!col.hidden"
                :disabled="col.disabled"
                :label="col.label"
                :prop="col.prop"
                :class="'form_' + col.prop"
              >
                <!-- 输入框 -->
                <div v-if="col.type === 'input'">
                  <c-input
                    v-model="formData[formIndex][col.prop]"
                    :size="size"
                    :placeholder="col.placeHolder || '请输入' + col.label"
                    :disabled="col.disabled"
                    clearable
                  >
                  </c-input>
                </div>

                <!-- 文本域 -->
                <div v-if="col.type === 'textarea'">
                  <c-input
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                    :placeholder="col.placeHolder || '请输入' + col.label"
                    rows="4"
                    type="textarea"
                  />
                </div>

                <!-- 下拉框 -->
                <div v-if="col.type === 'select'">
                  <c-select
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    clearable
                    :filterable="col.filterable"
                    :size="size"
                    :placeholder="col.placeHolder || '请选择' + col.label"
                  >
                    <c-option
                      v-for="(select, index) in col.list"
                      :key="`${index}key`"
                      :label="select.label"
                      :value="
                        col.returnValueType === 'all' ? select : select.value
                      "
                    />
                  </c-select>
                </div>

                <!-- 下拉多选 -->
                <div v-if="col.type === 'selectPlus'">
                  <c-select
                    v-model="formData[formIndex][col.prop]"
                    multiple
                    :disabled="col.disabled"
                    :size="size"
                    clearable
                    :placeholder="col.placeHolder || '请选择' + col.label"
                  >
                    <c-option
                      v-for="select in col.list"
                      :key="select.value"
                      :label="select.label"
                      :value="
                        col.returnValueType === 'all' ? select : select.value
                      "
                    />
                  </c-select>
                </div>

                <!-- 级联选择 -->
                <div v-if="col.type === 'cascader'">
                  <c-cascader
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                    clearable
                    :placeholder="col.placeHolder || '请选择' + col.label"
                    :options="col.list"
                    :props="col.cascaderProps"
                  />
                </div>

                <!-- 单选框组 -->
                <div v-if="col.type === 'radio'">
                  <c-radio
                    v-for="radio in col.list"
                    :key="radio.value"
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                    :label="radio.value"
                  >
                    {{ radio.label }}
                  </c-radio>
                </div>

                <!-- 多选框组 -->
                <div v-if="col.type === 'checkbox'">
                  <c-checkbox-group
                    v-model="formData[formIndex][col.prop]"
                    :size="size"
                    :disabled="col.disabled"
                  >
                    <c-checkbox
                      v-for="checkbox in col.list"
                      :key="checkbox.value"
                      :label="checkbox.value"
                    >
                      {{ checkbox.label }}
                    </c-checkbox>
                  </c-checkbox-group>
                </div>

                <!-- 日期点选择 2021-12-12 22:22:22 -->
                <div v-if="col.type === 'timePoint'">
                  <c-date-picker
                    v-model="formData[formIndex][col.prop]"
                    :size="size"
                    :disabled="col.disabled"
                    clearable
                    :value-format="col.valueFormat || 'yyyy-MM-dd HH:mm:ss'"
                    type="datetime"
                    :placeholder="col.placeHolder || '请选择' + col.label"
                  />
                </div>

                <!-- 日期选择 2022-12-12 -->
                <div v-if="col.type === 'datePoint'">
                  <c-date-picker
                    v-model="formData[formIndex][col.prop]"
                    clearable
                    :disabled="col.disabled"
                    :size="size"
                    :value-format="col.valueFormat || 'yyyy-MM-dd'"
                    type="date"
                    :placeholder="col.placeHolder || '请选择' + col.label"
                  />
                </div>

                <!-- 月份选择 -->
                <div v-if="col.type === 'month'">
                  <c-date-picker
                    v-model="formData[formIndex][col.prop]"
                    clearable
                    :disabled="col.disabled"
                    :size="size"
                    :value-format="col.valueFormat || 'yyyy-MM'"
                    type="month"
                    :placeholder="col.placeHolder || '请选择' + col.label"
                  />
                </div>

                <!-- 日期段选择 -->
                <div v-if="col.type === 'timePart'">
                  <c-date-picker
                    v-model="formData[formIndex][col.prop]"
                    :size="size"
                    :placeholder="col.placeHolder || '请选择' + col.label"
                    :disabled="col.disabled"
                    clearable
                    :value-format="col.valueFormat || 'yyyy-MM-dd HH:mm:ss'"
                    type="datetimerange"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                  />
                </div>

                <!-- 滑块 -->
                <div v-if="col.type === 'slider'">
                  <c-slider
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                  />
                </div>

                <!-- 评分 -->
                <div v-if="col.type === 'rate'" class="myRate">
                  <c-rate
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                  />
                </div>

                <!-- 开关 -->
                <div v-if="col.type === 'switch'">
                  <c-switch
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                  />
                </div>

                <!-- 颜色选择器 -->
                <div v-if="col.type === 'color'">
                  <c-color-picker
                    v-model="formData[formIndex][col.prop]"
                    :disabled="col.disabled"
                    :size="size"
                  />
                </div>

                <!-- 文件上传 -->
                <div v-if="col.type === 'upload'">
                  <filePreview
                    :ref="'filePreview' + col.prop + formIndex"
                    :readonly="readonly"
                    :action="action"
                    :service="service"
                    v-bind="col"
                    @change="
                      (fileList) =>
                        fileChange(fileList, formIndex, colIndex, col)
                    "
                  />
                </div>

                <!-- 插槽 -->
                <div v-if="col.type === 'slot'">
                  <slot
                    :name="col.slotName"
                    :[col.slotName]="{
                      $formIndex: formIndex,
                      $rowIndex: rowIndex,
                      $colIndex: colIndex,
                      formData: formData[formIndex],
                      $option: col
                    }"
                  />
                </div>
              </c-form-item>
            </c-col>
          </c-row>
        </c-form>
      </div>
      <!-- 底部 插槽 -->
      <div class="footer">
        <slot
          v-if="formPanel.footerSlotName"
          :name="formPanel.footerSlotName"
          :[formPanel.footerSlotName]="formPanel"
        />
      </div>
    </div>
  </div>
</template>

<script>
import filePreview from './filePreview'
import { handleMessage, findPattern } from './utils'

export default {
  name: 'MyForm',
  components: {
    filePreview
  },
  props: {
    readonly: {
      type: Boolean,
      default: () => false
    },
    limit: {
      type: Number
    },
    labelPosition: {
      type: String,
      default: () => 'left'
    },
    // labelWidth
    labelWidth: {
      type: String,
      default: () => ''
    },
    // 回填数据
    defaultData: {
      type: Array,
      default: () => []
    },
    size: {
      type: String,
      default: () => 'small'
    },
    // 表单配置
    option: {
      type: Array,
      default: () => []
    },
    // request 实例
    requestService: {
      type: Function,
      default: () => () => {}
    },
    // 文件上传地址
    action: {
      type: String,
      default: () => '#'
    },
    // 回填文件处理 需要return 图片地址
    previewHandle: {
      type: [Function, Boolean],
      default: false
    },
    // 文件处理
    fileHandle: {
      type: [Function, Boolean],
      default: false
    }
  },
  data () {
    return {
      unWather: null,
      formData: [],
      rules: []
    }
  },
  computed: {
    service () {
      return this.requestService
    }
  },
  created () {
    this.defaultValueUnWather = this.$watch(
      function () {
        return this.defaultData
      },
      // eslint-disable-next-line func-names, space-before-function-paren
      function (val) {
        if (val === null && this.defaultValueUnWather === null) return
        if (Array.isArray(val) && val.length > 0) {
          this.initData(true)
        } else {
          this.initData(false)
        }
        this.defaultValueUnWather()
      }
    )

    // this.optionUnWather = this.$watch(
    //   function () {
    //     return this.option
    //   },
    //   // eslint-disable-next-line func-names, space-before-function-paren
    //   function (val) {
    //     console.log(val, 'valll')
    //     if (Array.isArray(val) && val.length > 0) {
    //       this.initData(true)
    //     } else {
    //       this.initData(false)
    //     }
    //   },
    //   {
    //     deep: true
    //   }
    // )

    this.initData(false)
  },

  methods: {
    // 初始化数据
    initData (isEdit) {
      this.formData = []
      this.rules = []
      this.option.forEach((panel, panelIndex) => {
        const formList = panel.formItem.flat(Infinity)
        const formData = {}
        const ruleData = {}
        formList.forEach((x) => {
          if (!x.prop) {
            return
          }
          // 设置校验规则
          const findPatternObj = findPattern(x)
          const rule = [
            {
              required: x.required !== false,
              message: handleMessage(x.type) + x.label,
              trigger: x.trigger || ['change', 'blur']
            }
          ]
          // 自定义校验
          if (x.validator) {
            rule.push({
              validator: x.validator,
              trigger: x.trigger || ['change', 'blur']
            })
          } else {
            rule.push({
              pattern: findPatternObj.pattern,
              message: findPatternObj.message,
              trigger: x.trigger || ['change', 'blur']
            })
          }
          ruleData[x.prop] = rule

          this.$nextTick(() => {
            // 监听
            if (x.on) {
              this.$watch(
                () => {
                  return this.formData[panelIndex][x.prop]
                },
                (val) => {
                  x.on(val, x)
                }
              )
            }
          })

          if (isEdit) {
            // 数据回填
            formData[x.prop] = this.handleEdit(x, panelIndex)
          } else {
            let defaultValue = null
            // 初始化表单数据
            if (x.type === 'checkbox' || x.type === 'selectPlus') {
              defaultValue = []
            }
            if (x.defaultValue) {
              defaultValue = x.defaultValue
            }
            formData[x.prop] = defaultValue
          }
        })

        this.formData.push(formData)
        this.rules.push(ruleData)
      })
    },
    fileChange (val, formIndex, colIndex, col) {
      // console.log('aaaaaaaaaaaaaa', val)
      if (this.fileHandle) {
        const result = this.fileHandle(val)
        this.formData[formIndex][col.prop] = result
      } else {
        this.formData[formIndex][col.prop] = val
          .map((x) => x.response.data.id)
          .join(',')
      }
      this.$refs.ruleForm[formIndex].validateField(col.prop)
    },
    // 数据回填
    handleEdit (item, index) {
      // 处理上传文件回填
      if (item.type === 'upload') {
        // eslint-disable-next-line space-before-function-paren
        const ref = this.$refs[`filePreview${item.prop}${index}`]
        let fileList
        if (this.previewHandle) {
          fileList = this.previewHandle(
            this.defaultData[index][item.prop],
            this.defaultData[index],
            item.prop
          )
          // console.log(fileList, 'filelist')
          ref[0].sourceFile = fileList.map((x) => ({
            raw: {
              type: x.type
            },
            response: {
              data: {
                id: x.id,
                url: x.url,
                fileUrl: x.url,
                fileName: x.fileName,
                fileId: x.fileId
              }
            },
            name: x.fileName,
            status: 'success',
            url: x.url
          }))
          ref[0].handleSourceFile()
          // if (item.limit) {
          //   ref[index].hideUpload = ref[index].fileList.length >= item.limit
          // } else {
          //   ref[index].hideUpload = ref[index].fileList.length >= 5
          // }
        }
      }
      return this.defaultData[index][item.prop] || null
    },
    // 表单提交
    submitForm (isValidate = true) {
      const forms = this.$refs.ruleForm
      if (isValidate) {
        const list = []
        // 校验表单
        forms.forEach((x) => {
          x.validate((result) => {
            list.push(result)
          })
        })
        if (!list.some((x) => !x)) {
          return Promise.resolve(this.formData)
        }
        return Promise.resolve(null)
      }
      // 不校验表单
      return Promise.resolve(this.formData)
    },
    // 移除表单校验
    resetValidate (index) {
      this.$refs.ruleForm[index].clearValidate()
    },
    // 清空表单验证
    clearValidate () {
      this.$refs.ruleForm.forEach((x) => {
        x.clearValidate()
      })
    },
    // 重置表单
    resetForm () {
      // 重置表单
      const forms = this.$refs.ruleForm
      forms.forEach((x, index) => {
        x.resetFields()
        this.$nextTick(() => {
          this.resetValidate(index)
        })
      })
      // 重置上传文件
      const refs = this.$refs
      Object.keys(refs).forEach((ref) => {
        if (ref.includes('filePreview')) {
          refs[ref][0].fileList = []
          refs[ref][0].hideUpload = false
        }
      })
    },
    setData (prop, data) {
      this.$set(this.formData[0], prop, data)
    }
  }
}
</script>

<style scoped lang="scss">
.formContainer {
  width: 100%;
  .tltle {
    line-height: 40px;
    color: #333;
    font-weight: 600;
    font-size: 16px;
  }
  .el-col {
    padding-right: 12px;
  }

  .el-select {
    width: 100%;
  }
  .el-cascader {
    width: 100%;
  }
  .el-date-editor {
    width: 100%;
    :deep(.el-range-input) {
      width: 49% !important;
    }
  }
  .myRate {
    display: flex;
    height: 40px;
    align-items: center;
  }
}
</style>
<style lang="scss">
.form_undefined {
  margin-bottom: 0px !important;
}
</style>
